/*
 * ImageExif class
 * Used to manipulate all the exif fields of an image
 * 
 */
package exifheader;

import java.io.IOException;
import org.apache.sanselan.*;
import org.apache.sanselan.common.IImageMetadata;
import org.apache.sanselan.formats.tiff.TiffImageMetadata;
import org.apache.sanselan.formats.jpeg.JpegImageMetadata;
import org.apache.sanselan.formats.tiff.write.TiffOutputSet;
import org.apache.sanselan.formats.tiff.constants.TiffConstants;
import org.apache.sanselan.formats.tiff.TiffField;
import org.apache.sanselan.formats.tiff.write.TiffOutputField;

/**
 *
 * @author Christian
 */
public class ImageExif {

    java.io.File jpgFile;                   // JPG file
    // Read and write EXIF classes
    TiffImageMetadata readExif;
    TiffOutputSet writeExif;
    // EXIF data
    java.lang.String jpgExifMake;           // Image make name (e.g. Nikon)
    java.lang.String jpgExifModel;          // Image model name (e.g. D90 )
    java.util.Date jpgExifOriginalDate;   // Date when image was created
    gpsData jpgExifGPSData;
    boolean jpgExifGPS;                     // Are GPS values set?
    java.lang.String jpgName;               // File name
    boolean ExifModified;                   // Has the EXIF been modified?
    // Date formatter
    java.text.SimpleDateFormat dateParser;

    /**
     *
     */
    public enum exifFields {

        /**
         * Original creation date EXIF field
         */
        dateEXIF,
        /**
         * GPS Longitude and Latitude data
         */
        gpsdataEXIF
    };

    /**
     * Constructor for class ImageExif
     *
     * @param jpgFile
     * @throws java.io.IOException
     * @throws ImageReadException
     * @throws ImageWriteException
     */
    public ImageExif(java.io.File jpgFile)
            throws java.io.IOException, ImageReadException, ImageWriteException {

        this.jpgFile = jpgFile;
        // Initialise parses for converting back and forth from date text to
        // date object
        dateParser = new java.text.SimpleDateFormat("yyyy:MM:dd HH:mm:ss");

        readFile();
    }

    /**
     * Reads the JPG file and populates class variables from EXIF info.
     * @throws org.apache.sanselan.ImageReadException
     * @throws java.io.IOException
     * @throws org.apache.sanselan.ImageWriteException
     */
    public void readFile()
            throws java.io.IOException, org.apache.sanselan.ImageReadException,
            org.apache.sanselan.ImageWriteException {
        //java.io.OutputStream os = null;
        jpgExifGPS = false;
        ExifModified = false;


        jpgName = jpgFile.getName();
        //TiffOutputSet outputSet = null;

        // note that metadata might be null if no metadata is found.
        IImageMetadata readMetadata = Sanselan.getMetadata(jpgFile);
        JpegImageMetadata jpegMetadata = (JpegImageMetadata) readMetadata;
        if (null != jpegMetadata) {
            // note that exif might be null if no Exif metadata is found.
            readExif = jpegMetadata.getExif();

            if (null != readExif) {
            }
            TiffField originalDate = readExif.findField(TiffConstants.EXIF_TAG_MAKE);
            jpgExifMake = (java.lang.String) originalDate.getValue();
            originalDate = readExif.findField(TiffConstants.EXIF_TAG_MODEL);
            jpgExifModel = (java.lang.String) originalDate.getValue();
            originalDate = readExif.findField(TiffConstants.EXIF_TAG_DATE_TIME_ORIGINAL);


            try {
                jpgExifOriginalDate = dateParser.parse((String) originalDate.getValue());
            } catch (java.text.ParseException e) {
            }

            //System.out.println("Original date: " + originalDate.getFieldTypeName());

            TiffImageMetadata.GPSInfo gpsInfo = readExif.getGPS();
            if (null != gpsInfo) {
                jpgExifGPS = true;
                //String gpsDescription = gpsInfo.toString();
                jpgExifGPSData = new gpsData(gpsInfo.getLatitudeAsDegreesNorth(),
                        gpsInfo.getLongitudeAsDegreesEast());
            }
            writeExif = readExif.getOutputSet();
        }

    }

    /**
     * Modifies the Exif information in a photo file
     * @param field 
     * @param value
     * @throws org.apache.sanselan.ImageWriteException
     */
    public void modifyExif(exifFields field, java.lang.Object value) throws org.apache.sanselan.ImageWriteException {

        switch (field) {
            case dateEXIF:
                if (value instanceof java.util.Date) {
                    ExifModified = true;
                }
                return;
            case gpsdataEXIF:
                if (value instanceof gpsData) {
                    gpsData gps = (gpsData) value;
                    // Example of how to add/update GPS info to output set.
                    // New York City
                    //double longitude = -74.0; // 74 degrees W (in Degrees East)
                    //double latitude = 40 + 43 / 60.0; // 40 degrees N (in Degrees North)
                    //writeExif.setGPSInDegrees(longitude, latitude);
                    writeExif.setGPSInDegrees(gps.getLatitude(), gps.getLongitude());
                    ExifModified = true;
                }
                return;
            //
        }

        // Example of how to remove a single tag/field.
        //
        // Note that this approach is crude: Exif data is organized in
        // directories.  The same tag/field may appear in more than one
        // directory.
        TiffOutputField date = writeExif.findField(TiffConstants.EXIF_TAG_DATE_TIME_ORIGINAL);

    }

    /**
     * Indicates whether or not the Exif data has been modified.
     * @return 
     */
    public boolean isModified() {
        return ExifModified;
    }

    /**
     * Prints the information in the Exif header of the file
     */
    public void showExif() {
        System.out.println("Filename: " + jpgName + " Date:" + jpgExifOriginalDate.toString());
        System.out.println("Make:" + jpgExifMake + " Model:" + jpgExifModel);
        if (jpgExifGPS) {
            System.out.println(jpgExifGPSData.googleSearch());
            //System.out.println(" Latitude:" + jpgExifLatitude + " Longitude:" + jpgExifLongitude);
        }
    }
}
